/*
 * iniconfig.c
 *
 *  Created on: 2012-05-23
 *      Author: Aco
 */

#include "iniconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Nadji stavku po "putanji", npr.
//
// [grupa]
// stavka=vrijednost
//
// ..bi se dobila kao "grupa/stavka"
ININode * ini_getNode(ININode * root, const char * name)
{
	char group[64] = {0}, *slashPos;
	if(root == NULL) return NULL;

	slashPos = strchr(name, '/');
	if(slashPos)
	{
		strncpy(group, name, (int)slashPos - (int)name);
		name = slashPos + 1;
	}

	while(root)
	{
		if(strcmp(root->group, group) == 0 && strcmp(root->key, name) == 0)
			return root;
		root = root->next;
	}
	return NULL;
}

// Uklanjanje spejsova, novih redova i sl.
void ini_rtrim(char * txt)
{
	int len, i;
	if(txt == NULL) return;
	len = strlen(txt);
	for(i = len - 1; i >= 0; --i)
		if(txt[i] == ' ' || txt[i] == '\n' || txt[i] == '\r')
			txt[i] = '\0';
		else
			break;
}

// Procitaj jedan INI file i sastavi vezanu listu njegovih stavki
ININode * ini_parseFile(const char * fileName)
{
	ININode *root = NULL, *current;
	FILE *f = fopen(fileName, "rt");
	char lineBuffer[512], *split;
	char group[64] = {0};
	int len;

	if(f == NULL)
		return NULL;

	root = (ININode*)calloc(1, sizeof(ININode));
	current = root;

	while(!feof(f))
	{
		fgets(lineBuffer, 512, f);	// Citaj liniju po liniju
		ini_rtrim(lineBuffer);
		len = strlen(lineBuffer);

		if(lineBuffer[0] == '#') continue; // Taraba je komentar

		if(lineBuffer[0] == '[')	// U srednjim zagradama je naziv odjeljka/grupe
		{
			split = strchr(lineBuffer, ']');
			if(split != NULL)
			{
				strncpy(group, lineBuffer + 1, (int)split - (int)lineBuffer - 1);
				group[(int)split - (int)lineBuffer - 1] = '\0';
			}
		}
		else
		{
			split = strchr(lineBuffer, '=');	// Inace, ako ima =, izvadi key i value
			if(split != NULL)
			{
				ININode *nnode = (ININode*)calloc(1, sizeof(ININode));
				strcpy(nnode->group, group);
				strncpy(nnode->key, lineBuffer, (int)split - (int)lineBuffer);
				nnode->key[(int)split - (int)lineBuffer] = '\0';
				strncpy(nnode->value, split + 1, (int)lineBuffer + len - (int)split);
				nnode->value[(int)lineBuffer + len - (int)split] = '\0';

				current->next = nnode;
				current = nnode;
			}
		}
	}

	fclose(f);
	return root;
}

// Potrazi string, ako nema, vrati dati default
const char * ini_getString(ININode * node, const char * path, const char * def)
{
	ININode * res = ini_getNode(node, path);
	if(res)
		return res->value;
	else
		return def;
}

// Potrazi i probaj procitati INT, ako nema, vrati dati default
int ini_getInt(ININode * node, const char * path, int def)
{
	ININode * res = ini_getNode(node, path);
	int ret = def;
	if(res)
		sscanf(res->value, "%d", &ret);
	return ret;
}

// Oslobodi memoriju za cijelu listu
void ini_destroy(ININode * node)
{
	ININode * next;
	while(node)
	{
		next = node->next;
		free(node);
		node = next;
	}
}
